`ifdef SIM
module sim_tb ();
    //iverilog -DSIM -f sim2.txt && vvp a.out
    reg clk = 0;
    reg rst_n = 0;
    reg memory_clk = 0;
    wire clk50m = clk;

    always clk = #10 ~clk;
    always memory_clk = #1.25 ~memory_clk;
    always rst_n = #100 1;
    always #140000 $finish;
    reg[31:0] counter = 0;

    localparam test_counter = 10;

`define counter_cmp(cnt) (counter==test_counter+cnt||counter==test_counter+cnt+1)
`define counter_cmp_range(cnt1,cnt2)        ((counter>=cnt1) && (counter<=cnt2))
//`define TEST_WRITE

    wire        sdio_clk;
    inout       sdio_cmd;
    reg         sdio_cmd_i = 1'bz;
    assign sdio_cmd = sdio_cmd_i;
    pullup(sdio_cmd);
    inout[3:0]   sdio_dat;
    pullup(sdio_dat[0]);
    pullup(sdio_dat[1]);
    pullup(sdio_dat[2]);
    pullup(sdio_dat[3]);
    reg [3:0] sdio_dat_i = 'hz;
    assign sdio_dat = sdio_dat_i;

    reg apb_psel = 0            ;
    reg[31:0]  apb_addr = 0     ;
    reg[31:0]  apb_pwdata =    0;
    wire[31:0] apb_prdata       ;
    reg apb_pwrite = 0          ;
    reg apb_ptran  = 0          ;

    task task_write;
        input[31:0] addr;
        input[31:0] data;
    begin
        apb_pwrite  <= 1;
        apb_psel    <= 1;
        apb_addr    <= addr;
        apb_pwdata  <= data;
        apb_ptran   <= 1;
    end
    endtask

    task task_read;
        input[31:0] addr;
    begin
        apb_pwrite  <= 0;
        apb_psel    <= 1;
        apb_addr    <= addr;
        apb_ptran   <= 1;
    end
    endtask

    function[31:0] cmd_gen;
        input[5:0] cmd;
        input need_rsp;
        input long_rsp;
    begin
        cmd_gen[31:0] = 0;
        cmd_gen[5:0] = cmd;
        cmd_gen[6] = need_rsp;
        cmd_gen[7] = long_rsp;
        cmd_gen[9] = 1;
    end
    endfunction

`define TEST_RSP                //测试RSP
//`define TEST_CLK_DIV          //测试分频
`define TEST_DAT_READ           //测试读取
    wire long_rsp = 0;

    always @(posedge clk) begin
        counter <= counter + 1;
        if(`counter_cmp(50))begin
            //重置命令
            //task_write(0,1<<10);
        end
        else if(`counter_cmp(500))begin
            `ifdef TEST_RSP
            //需要rsp
            task_write(0,cmd_gen(55,1,long_rsp));
            `else
            //发送一个不需要rsp的命令
            task_write(0,cmd_gen(55,0,0));
            `endif
            sdio_dat_i <= 0;
        end
        `ifdef TEST_CLK_DIV
        else if(`counter_cmp(20))begin
            task_write('h38,20);
        end
        `endif
        `ifdef TEST_RSP
        else if(`counter_cmp(300))begin
            sdio_cmd_i <= 0;
        end
        `endif
        `ifdef TEST_DAT_READ
        else if(`counter_cmp(94))begin
            //先设置数据寄存器
            task_write('h1c,
                 (1<<6)          //数据开启
                |(9)             //数据大小,8 = 1<<3
            );
        end
        else if(`counter_cmp(100))begin
            //发送命令
            task_write(0,cmd_gen(55,1,0));
        end
        else if(`counter_cmp(1400))begin
            task_write('h1c,
            (1<<6)          //数据开启
            |(1<<10)        //重置fifo
            |(9)
            );
        end
        else if(`counter_cmp(1420))begin
            task_write('h1c,
            (1<<6)          //数据开启
            |(9)
            );
        end
        else if(`counter_cmp(1700))begin
            //触发一次读取,fifo已经满了
            task_read('h40);
        end
        else if(`counter_cmp(1750))begin
            //触发一次读取,fifo已经满了
            task_read('h40);
        end
        `endif
        else begin
            apb_pwrite <= 0;
            apb_ptran  <= 0;
            apb_psel   <= 0;
            sdio_cmd_i  <= 1'bz;
            sdio_dat_i  <= 4'bz;
        end
    end

    ftsdc010_sim u_ftsdc010_sim(
        .sdio_clk       (sdio_clk)      ,
        .sdio_cmd       (sdio_cmd)      ,
        .sdio_dat       (sdio_dat)      ,
        .apb_psel       (apb_psel       ),
        .apb_addr       (apb_addr       ),
        .apb_pwdata     (apb_pwdata     ),
        .apb_prdata     (apb_prdata     ),
        .apb_pwrite     (apb_pwrite     ),
        .apb_ptran      (apb_ptran      ),
        .apb_pready_o   (apb_pready_o   ),
        .clk            (clk            ),
        .reset          (~rst_n         )
    );

    initial begin
        $dumpfile("test.vcd");
        $dumpvars(0, sim_tb);
    end
endmodule
`endif
